// UvPropPage.cpp : implementation file
//

#include "stdafx.h"
#include "const.h"
#include "UvPropPage.h"

#include "ArchiveRead.h"
#include "CFile64.h"
#include "gp_uv_rc.h"
#include "InclusionDlgOffset.h"
#include "AreaUtils.h"

#include <bitset>
using namespace std;

using namespace nsExclusionStatic2;
using namespace nsAreaUtils;

extern void DLL_CALLCONV MG_ActToRgbquad( RGBQUAD *pRgbQuad, BYTE *pPal, DWORD dwCount );

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CUvPropPage property page

IMPLEMENT_DYNCREATE(CUvPropPage, CPropertyPage)

MGBITMAP *loadBmpToBitmapPtr( LPCTSTR pszFileName, RGBQUAD *pExtPal = 0  )
{
	MGBITMAP *pBmp = 0;

	// search for file
	tInStream FileIn;
	CMyFileException e;
	if( FileIn.Open( pszFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &e ) )
	{
		DWORD dwFileLength = (DWORD)FileIn.GetLength();

		CMemBuffer mb;
		pBmp = mb.getBmpFileFromStream( &FileIn, dwFileLength, false, pExtPal );

		FileIn.Close();
	}

	return pBmp;
}


CUvPropPage::CUvPropPage() : CPropertyPage(CUvPropPage::IDD)
{
	//{{AFX_DATA_INIT(CUvPropPage)
	m_lImageFront = FALSE;
	m_lImageBack = FALSE;
	m_lAreaFront = FALSE;
	m_lAreaBack = FALSE;
	m_lSecondPageFront = FALSE;
	m_lSecondPageBack = FALSE;
	m_strImageFront = _T("");
	m_strImageBack = _T("");
	m_lMacFront = -1;
	m_lMacBack = -1;
	//}}AFX_DATA_INIT

	m_pBmpUvImageFront = 0;
	m_pBmpUvImageBack = 0;
	m_pBmpUvImageFrontDisplay = 0;
	m_pBmpUvImageBackDisplay = 0;
	pPaletteUv4_ = new RGBQUAD[ 256 ];

	m_pInclusionDlgOffset = 0;

	m_bUpdateLocked = FALSE;

	m_bInitialized = FALSE;

	m_IniPathIndex.setOptionPath();

	setupOptions();
}

CUvPropPage::~CUvPropPage()
{
	if ( m_pBmpUvImageFront ) MG_Unload( m_pBmpUvImageFront );
	if ( m_pBmpUvImageBack ) MG_Unload( m_pBmpUvImageBack );
	if ( m_pBmpUvImageFrontDisplay ) MG_Unload( m_pBmpUvImageFrontDisplay );
	if ( m_pBmpUvImageBackDisplay ) MG_Unload( m_pBmpUvImageBackDisplay );
	if ( pPaletteUv4_ ) delete[] pPaletteUv4_;
	if ( m_pInclusionDlgOffset ) delete m_pInclusionDlgOffset;
}

void CUvPropPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CUvPropPage)
	DDX_Control(pDX, IDC_PIC_UV_IMAGE_BACK, m_picImageBack);
	DDX_Control(pDX, IDC_PIC_UV_IMAGE_FRONT, m_picImageFront);
	DDX_Control(pDX, IDC_PIC_UV_AREA_FRONT, m_picAreaFront);
	DDX_Control(pDX, IDC_PIC_UV_AREA_BACK, m_picAreaBack);
	DDX_Control(pDX, IDC_ST_UVPP_BACK, m_stBack);
	DDX_Control(pDX, IDC_ST_UVPP_FRONT, m_stFront);
	DDX_Control(pDX, IDC_ST_UVPP_METHOD, m_stMethod);
	DDX_Check(pDX, IDC_CB_UV_IMAGE_FRONT, m_lImageFront);
	DDX_Check(pDX, IDC_CB_UV_IMAGE_BACK, m_lImageBack);
	DDX_Check(pDX, IDC_CB_UV_AREA_FRONT, m_lAreaFront);
	DDX_Check(pDX, IDC_CB_UV_AREA_BACK, m_lAreaBack);
	DDX_Check(pDX, IDC_CB_UV_SECOND_PAGE_FRONT, m_lSecondPageFront);
	DDX_Check(pDX, IDC_CB_UV_SECOND_PAGE_BACK, m_lSecondPageBack);
	DDX_Text(pDX, IDC_EF_UV_IMAGE_FRONT, m_strImageFront);
	DDX_Text(pDX, IDC_EF_UV_IMAGE_BACK, m_strImageBack);
	DDX_Radio(pDX, IDC_RG_UV_MAC_FRONT_A, m_lMacFront);
	DDX_Radio(pDX, IDC_RG_UV_MAC_BACK_A, m_lMacBack);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CUvPropPage, CPropertyPage)

	//{{AFX_MSG_MAP(CUvPropPage)
	ON_BN_CLICKED(IDC_CB_UV_IMAGE_FRONT, OnCbImageFront)
	ON_BN_CLICKED(IDC_CB_UV_IMAGE_BACK, OnCbImageBack)
	ON_BN_CLICKED(IDC_CB_UV_AREA_FRONT, OnCbAreaFront)
	ON_BN_CLICKED(IDC_CB_UV_AREA_BACK, OnCbAreaBack)
	ON_BN_CLICKED(IDC_CB_UV_SECOND_PAGE_FRONT, OnCbSecondPageFront)
	ON_BN_CLICKED(IDC_CB_UV_SECOND_PAGE_BACK, OnCbSecondPageBack)
	ON_BN_CLICKED(IDC_PB_UV_IMAGE_FRONT, OnPbImageFront)
	ON_BN_CLICKED(IDC_PB_UV_IMAGE_BACK, OnPbImageBack)
	ON_BN_CLICKED(IDC_PIC_UV_AREA_FRONT, OnPicAreaFront)
	ON_BN_CLICKED(IDC_PIC_UV_AREA_BACK, OnPicAreaBack)
	ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_UPDATE_CONTROL, OnUpdateControl)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CUvPropPage message handlers

BOOL CUvPropPage::OnApply()
{
	if ( m_bInitialized ) {
		if(!UpdateData( DISPLAY2DATA ))
			return FALSE;
		DisplayToDevmod();
	}

	return CPropertyPage::OnApply();
}

BOOL CUvPropPage::OnKillActive() 
{
	if(!UpdateData( DISPLAY2DATA ))
		return FALSE;

#ifndef UI_EXE
	PropPageSetResult();				
#else
	DisplayToDevmod();
#endif

	return CPropertyPage::OnKillActive();
}

BOOL CUvPropPage::OnSetActive() 
{
	UpdateFields();

	return CPropertyPage::OnSetActive();
}

void CUvPropPage::PropPageSetResult()
{
	OnApply();
	DWORD result = CPSUI_OK; 
	if(pfnComPropSheet)
		if ((pfnComPropSheet(hComPropSheet,
			CPSFUNC_SET_RESULT,
			(LPARAM)pfnHandle,
			result)) == NULL){
		}
}

void CUvPropPage::SetEnabledBack()
{
	// modify PrintBack-Bit for K/PO panel
	bitset<elBits> UISettings( m_lpDM->UISettings );

	if ( UISettings[ elBackEnabled ] != m_bBackEnabled )
	{
		m_bBackEnabled = UISettings[ elBackEnabled ];

		m_SC.SetID( IDC_CB_UV_IMAGE_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_EF_UV_IMAGE_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_PB_UV_IMAGE_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_PIC_UV_IMAGE_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_CB_UV_SECOND_PAGE_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_CB_UV_AREA_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_PIC_UV_AREA_BACK, m_bBackEnabled );
		m_SC.SetID( IDC_RG_UV_MAC_BACK_A, m_bBackEnabled );
		m_SC.SetID( IDC_RG_UV_MAC_BACK_B, m_bBackEnabled );
		UpdateControls( eueUvForceUpdate );
	}
}

BOOL CUvPropPage::OnInitDialog() 
{
	m_bProhibit_560_570_Features = DriverType == XID560Drv || DriverType == XID570Drv ? TRUE : FALSE;
	nAreaCountMax_ = sizeof( m_lpDM->UvAreas ) / sizeof( SPEC_AREA );

	Init();

	DevmodToDisplay();

	CPropertyPage::OnInitDialog();

	if ( m_pInclusionDlgOffset == NULL )
	{
		m_pInclusionDlgOffset = new CInclusionDlgOffset( true, this );
	}

	m_stMethod.SetPrnDrvTheme();
	m_stFront.SetFontBold( TRUE );
	m_stFront.ModifyStyleEx( WS_EX_STATICEDGE, NULL );
	m_stBack.SetFontBold( TRUE );
	m_stBack.ModifyStyleEx( WS_EX_STATICEDGE, NULL );

	m_Sep[ 0 ].SubclassDlgItem( IDC_ST_UV_SPLIT1, this );
	m_Sep[ 1 ].SubclassDlgItem( IDC_ST_UV_SPLIT2, this );
	m_Sep[ 2 ].SubclassDlgItem( IDC_ST_UV_SPLIT3, this );
	m_Sep[ 3 ].SubclassDlgItem( IDC_ST_UV_SPLIT4, this );
	m_Sep[ 4 ].SubclassDlgItem( IDC_ST_UV_SPLIT5, this );

	// use pure green as chroma color (not present in UV palette)
	chroma[ 0 ] = 0;
	chroma[ 1 ] = 255;
	chroma[ 2 ] = 0;
	chroma[ 3 ] = 0;
	m_picImageFront.SetMaskColor( chroma );
	m_picImageBack.SetMaskColor( chroma );

	// set UV area
	vpAreaST_.push_back( &m_picAreaFront );
	vpAreaST_.push_back( &m_picAreaBack );

	tvExclusionST2::const_iterator it = vpAreaST_.begin(),
		end = vpAreaST_.end();
	CExclusionST2 *pWnd;

	while ( it != end )
	{
		pWnd = *it++;
		pWnd->Init( 
			true,		// thumb mode
			eb3DRaised,	// border
			false,		// show empty
			true );		// has offset
		pWnd->ClipBorders();
	}


	// load UV palette for display from resource
	// pPaletteUv3 = 3-byte palette
	// pPaletteUv4_ = 4-byte palette (RGBQUAD)
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC res = FindResource( hInst, MAKEINTRESOURCE( IDR_PALETTE_UV ), _T( "BIN" ) );
	HGLOBAL res_handle = LoadResource( hInst, res );
	BYTE *pPaletteUv3 = (BYTE *)LockResource( res_handle );
	MG_ActToRgbquad( pPaletteUv4_, pPaletteUv3, 256 );

	m_bInitialized = TRUE;

	// load images but don't show any errors
	setUvFromImageForSide( strImageFrontFull_, eusFront, false );
	setUvFromImageForSide( strImageBackFull_, eusBack, false );

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CUvPropPage::SetCheck( DWORD IDC, BOOL bValue /*= TRUE*/ )
{
	((CButton*) GetDlgItem(IDC))->SetCheck( bValue );
}

BOOL CUvPropPage::isChecked(DWORD IDC)
{	
	return ((CButton*) GetDlgItem(IDC))->GetCheck();
}

BOOL CUvPropPage::isEnabled( DWORD IDC )
{
	return GetDlgItem( IDC )->IsWindowEnabled();
}

void CUvPropPage::Init()
{
	m_bBackEnabled = TRUE;

	nDPI_ = ThePrintQuality;

	Areas_[ 0 ][ esFront ].iCurrentExclusion =
	Areas_[ 0 ][ esBack ].iCurrentExclusion = -1;

	m_SC.SetID( IDC_CB_UV_IMAGE_FRONT, true );
	m_SC.SetID( IDC_EF_UV_IMAGE_FRONT, true ); // edit fields are enabled but read only!!!
	m_SC.SetID( IDC_PB_UV_IMAGE_FRONT, true );
	m_SC.SetID( IDC_PIC_UV_IMAGE_FRONT, true );
	m_SC.SetID( IDC_CB_UV_SECOND_PAGE_FRONT, true );
	m_SC.SetID( IDC_CB_UV_AREA_FRONT, true );
	m_SC.SetID( IDC_RG_UV_MAC_FRONT_A, true );
	m_SC.SetID( IDC_RG_UV_MAC_FRONT_B, true );
	m_SC.SetID( IDC_CB_UV_IMAGE_BACK, true );
	m_SC.SetID( IDC_EF_UV_IMAGE_BACK, true );
	m_SC.SetID( IDC_PB_UV_IMAGE_BACK, true );
	m_SC.SetID( IDC_PIC_UV_IMAGE_BACK, true );
	m_SC.SetID( IDC_CB_UV_SECOND_PAGE_BACK, true );
	m_SC.SetID( IDC_CB_UV_AREA_BACK, true );
	m_SC.SetID( IDC_PIC_UV_AREA_BACK, true );
	m_SC.SetID( IDC_RG_UV_MAC_BACK_A, true );
	m_SC.SetID( IDC_RG_UV_MAC_BACK_B, true );
}

void CUvPropPage::OnCbImageFront() 
{
	// selects this as the only option
	// selectOption cally UpdateControls to disable previously selected option
	// and UpdateControls to enable this option
	selectOption( eusFront, euoImage, isChecked( IDC_CB_UV_IMAGE_FRONT ) );
}

void CUvPropPage::OnCbImageBack() 
{
	selectOption( eusBack, euoImage, isChecked( IDC_CB_UV_IMAGE_BACK ) );
}

void CUvPropPage::OnCbAreaFront() 
{
	selectOption( eusFront, euoArea, isChecked( IDC_CB_UV_AREA_FRONT ) );
}

void CUvPropPage::OnCbAreaBack() 
{
	selectOption( eusBack, euoArea, isChecked( IDC_CB_UV_AREA_BACK ) );
}

void CUvPropPage::OnCbSecondPageFront() 
{
	selectOption( eusFront, euoSecondPage, isChecked( IDC_CB_UV_SECOND_PAGE_FRONT ) );
}

void CUvPropPage::OnCbSecondPageBack() 
{
	selectOption( eusBack, euoSecondPage, isChecked( IDC_CB_UV_SECOND_PAGE_BACK ) );
}


void CUvPropPage::OnPbImageFront() 
{
	UpdateData( DISPLAY2DATA );
	CString strOld( strImageFrontFull_ );

	if ( browseForBmpFile( &strImageFrontFull_ ) )
	{
		if ( !setUvFromImageForSide( strImageFrontFull_, eusFront, true ) )
		{
			strImageFrontFull_ = strOld;
			CFile64::ExtractFileName( m_strImageFront, strOld );
		}

		// update image name
		UpdateData( DATA2DISPLAY );
		OnCbImageFront();
	}
}

void CUvPropPage::OnPbImageBack() 
{
	UpdateData( DISPLAY2DATA );
	CString strOld( strImageBackFull_ );

	if ( browseForBmpFile( &strImageBackFull_ ) )
	{
		if ( !setUvFromImageForSide( strImageBackFull_, eusBack, true ) )
		{
			strImageBackFull_ = strOld;
			CFile64::ExtractFileName( m_strImageFront, strOld );
		}

		// update image name
		UpdateData( DATA2DISPLAY );
		OnCbImageBack();
	}
}

HBRUSH CUvPropPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor);
	// draw transparent background for CLabel
	if (nCtlColor == CTLCOLOR_STATIC)
	{
		int nId = pWnd->GetDlgCtrlID();
		switch( nId )
		{
			case IDC_ST_UVPP_FRONT:
			case IDC_ST_UVPP_BACK:
				{
					CLabel *pLabel = (CLabel *)pWnd;

					if ( pLabel->m_crBkgnd == CTLCOLOR_STATIC )
					{
						CRect rc;
						pWnd->GetClientRect(rc);
						pDC->BitBlt(0, 0, rc.right - rc.left, rc.bottom - rc.top, 
						pWnd->GetDC(), rc.left, rc.top, SRCCOPY);
					}
					pDC->SetBkMode(TRANSPARENT);
					return (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
				}
		}

	}

	return hbr;
}

LRESULT CUvPropPage::OnUpdateControl(WPARAM wParam, LPARAM lParam)
{
	// create a copy of the image
	// to draw the "enabled" look
	if ( m_pBmpUvImageFront )
	{
#ifdef XXX
		if ( m_pBmpUvImageFrontDisplay ) MG_Unload( m_pBmpUvImageFrontDisplay );
		int nx = MG_GetWidth( m_pBmpUvImageFront ),
			ny = MG_GetHeight( m_pBmpUvImageFront );
		m_pBmpUvImageFrontDisplay = MG_Allocate( nx, ny );

		DWORD rgb = 0x80ffffff; MG_setColor( (BYTE *)&rgb );
		MG_Box( m_pBmpUvImageFrontDisplay, 0, 0, nx, ny );
		MG_BoxA( m_pBmpUvImageFront, 0, 0, nx, ny );
		MG_CopyA( m_pBmpUvImageFrontDisplay, m_pBmpUvImageFront, 0, 0, nx, ny, 0, 0 );
		rgb = 0xff000000; MG_setColor( (BYTE *)&rgb );
		MG_BoxA( m_pBmpUvImageFront, 0, 0, nx, ny );

/*
		if ( !GetCheck( IDC_CB_UV_IMAGE_FRONT ) ) {
			DWORD rgb = 0x80ffffff; MG_setColor( (BYTE *)&rgb );
			MG_Box( m_pBmpUvImageFrontDisplay, 0, 0, nx, ny );
		}
*/
		m_picImageFront.SetBaseImage( m_pBmpUvImageFrontDisplay );
#endif // XXX
		m_picImageFront.SetBaseImage( m_pBmpUvImageFront );
	}

	if ( m_pBmpUvImageBack )
	{
		m_picImageBack.SetBaseImage( m_pBmpUvImageBack );
	}

#ifdef XXX
	{
		POINT outer = { 100, 50 },
			  dst = { 300, 100 };
		RECT inner = { 10, 10, 40, 80 };

		fitRect( outer, inner, dst );
		int x = 5;
	}

	{
		POINT outer = { 50, 100 },
			  dst = { 100, 300 };
		RECT inner = { 10, 10, 80, 40 };

		fitRect( outer, inner, dst );
		int x = 5;
	}
#endif // XXX


	return 0;
}

void CUvPropPage::DisplayToDevmod()
{
	UpdateData( DISPLAY2DATA );

	// UV options
	bitset<euvBits> UvBits;
	UvBits[ euvPageSplit ] = m_lSecondPageFront ? true : false;
	UvBits[ euvImageFile ] = m_lImageFront ? true : false;
	UvBits[ euvAreaOffset ] = m_lAreaFront ? true : false;
	UvBits[ euvMacArea ] = m_lMacFront ? true : false;
	m_lpDM->FrontUV = (BYTE)UvBits.to_ulong();

	UvBits.reset();
	UvBits[ euvPageSplit ] = m_lSecondPageBack ? true : false;
	UvBits[ euvImageFile ] = m_lImageBack ? true : false;
	UvBits[ euvAreaOffset ] = m_lAreaBack ? true : false;
	UvBits[ euvMacArea ] = m_lMacBack ? true : false;
	m_lpDM->BackUV = (BYTE)UvBits.to_ulong();

//	g_Tracer.MakeTrace( _T("UN: written to devmod: FrontUV=%d BackUV=%d"), m_lpDM->FrontUV, m_lpDM->BackUV );

	DWORD dwNewMachineId; // will become a new machine ID, if none is set in INI
                          // file or the machine ID from the INI file
	// check if a path is set
	if ( !strImageFrontFull_.IsEmpty() )
	{
		// check if we have already an assigned path
		if ( m_dwPathIndexFront == 0 ) m_IniPathIndex.getNewPathIndex( &m_dwPathIndexFront );
		// save path
		m_IniPathIndex.storePathAsIndex( &dwNewMachineId, m_dwPathIndexFront, strImageFrontFull_ );

		ASSERTR( sizeof( unsigned short ) == 2 ); // unsigned short must be 16-bits (2 bytes)
		*(unsigned short *)&m_lpDM->PathIndexFront = (unsigned short)m_dwPathIndexFront;
	}

	// the same for back
	if ( !strImageBackFull_.IsEmpty() )
	{
		// check if we have already an assigned path
		if ( m_dwPathIndexBack == 0 ) m_IniPathIndex.getNewPathIndex( &m_dwPathIndexBack );
		// save path
		m_IniPathIndex.storePathAsIndex( &dwNewMachineId, m_dwPathIndexBack, strImageBackFull_ );

		ASSERTR( sizeof( unsigned short ) == 2 ); // unsigned short must be 16-bits (2 bytes)
		*(unsigned short *)&m_lpDM->PathIndexBack = (unsigned short)m_dwPathIndexBack;
	}

	// if no machine ID was set in DEVMODE or machine ID differs (i.e. DEVMODE
    // is from another machine), we overwrite the machine ID in DEVMODE with the
    // current
	if ( m_dwMachineID == 0 || m_dwMachineID != dwNewMachineId )
	{
		m_dwMachineID = dwNewMachineId;
		*(unsigned short *)&m_lpDM->MachineID = (unsigned short)m_dwMachineID;
	}


	// UV offset areas
	vector<SPEC_AREA> vArea;
	getAreasFromArray( vArea, esFront, Areas_[ 0 ][ esFront ] );
	getAreasFromArray( vArea, esBack, Areas_[ 0 ][ esBack ] );
	setAreasToDevmod( &m_lpDM->UvAreas[ 0 ], vArea, nAreaCountMax_ );
}

void CUvPropPage::DevmodToDisplay()
{
	// UV options
	bitset<euvBits> UvBits( m_lpDM->FrontUV );
	m_lSecondPageFront = UvBits[ euvPageSplit ] ? 1 : 0;
	m_lImageFront = UvBits[ euvImageFile ] ? 1 : 0;
	m_lAreaFront = UvBits[ euvAreaOffset ] ? 1 : 0;
	m_lMacFront = UvBits[ euvMacArea ] ? 1 : 0;

	UvBits = m_lpDM->BackUV;
	m_lSecondPageBack = UvBits[ euvPageSplit ] ? 1 : 0;
	m_lImageBack = UvBits[ euvImageFile ] ? 1 : 0;
	m_lAreaBack = UvBits[ euvAreaOffset ] ? 1 : 0;
	m_lMacBack = UvBits[ euvMacArea ] ? 1 : 0;

	ASSERTR( sizeof( unsigned short ) == 2 ); // unsigned short must be 16-bits (2 bytes)

	m_dwPathIndexFront = *(unsigned short *)&m_lpDM->PathIndexFront;
	m_dwMachineID = *(unsigned short *)&m_lpDM->MachineID;
	if ( !m_IniPathIndex.getPathFromIndex( &strImageFrontFull_, m_dwPathIndexFront, m_dwMachineID ) )
	{
		strImageFrontFull_ = _T( "" );
		m_dwPathIndexFront = 0;
	}
	// make display name
	CFile64::ExtractFileName( m_strImageFront, strImageFrontFull_ );

	m_dwPathIndexBack = *(unsigned short *)&m_lpDM->PathIndexBack;
	if ( !m_IniPathIndex.getPathFromIndex( &strImageBackFull_, m_dwPathIndexBack, m_dwMachineID ) )
	{
		strImageBackFull_ = _T( "" );
		m_dwPathIndexBack = 0;
	}
	CFile64::ExtractFileName( m_strImageBack, strImageBackFull_ );


	setAreasToArrayFromDevmod( &Areas_[ 0 ][ esFront ], &m_lpDM->UvAreas[ 0 ], nAreaCountMax_ );



	if ( m_bInitialized ) UpdateFields();
}

void CUvPropPage::UpdateFields()
{
	UpdateData( DATA2DISPLAY );

	SetEnabledBack(); // the checkboxes must be updated immediately because the
                      // enabling of the back-side radio groups depends on the
                      // enabled-state of the checkboxes

	setOrientation();

	m_bUpdateLocked = TRUE;
	UpdateControls( eueUvImageFront_Changed );
	UpdateControls( eueUvImageBack_Changed );
	UpdateControls( eueUvAreaFront_Changed );
	UpdateControls( eueUvAreaBack_Changed );
	UpdateControls( eueUvSecondPageFront_Changed );
	UpdateControls( eueUvSecondPageBack_Changed );

	m_picAreaFront.SetExclusionAreasFrom( &Areas_[ 0 ][ esFront ] );
	m_picAreaBack.SetExclusionAreasFrom( &Areas_[ 0 ][ esBack ] );

	m_bUpdateLocked = FALSE;

	//	UpdateImages();
	UpdateControls( eueUvForceUpdate );

	//	OnCBEncCtrlClicked();
}

void CUvPropPage::UpdateControls( EUVUPDATEEVENT Event )
{
	static bool bUpdateRunning = false;

/*
	static int lLastEncodingControl = -1;
*/

	bitset<elBits> UISettings( m_lpDM->UISettings );
	bool bCardHasEncoding = UISettings[ elMagstripe ] || UISettings[ elSmartChip ];
	bool bEncodeOnly = bCardHasEncoding && ( ( m_lpDM->UIEncodingControl & 3 ) == 1 );

	// avoid re-entrance while handling update
	if ( !bUpdateRunning )
	{
		bool bUpdateNeeded = false;		// set to true if controls are enabled / disabled
		bool bChecked;

		bUpdateRunning = true;
		UpdateData( DISPLAY2DATA );

		// first, determine what was clicked and choose what has to be changed
		switch( Event )
		{
			case eueUvForceUpdate:
				bUpdateNeeded = true;
				break;
			case eueUvImageFront_Changed:
				{
					bool bChecked = isChecked( IDC_CB_UV_IMAGE_FRONT ) ? true : false;
					m_SC.SetID( IDC_EF_UV_IMAGE_FRONT, bChecked );
					m_SC.SetID( IDC_PB_UV_IMAGE_FRONT, bChecked );
					m_SC.SetID( IDC_PIC_UV_IMAGE_FRONT, bChecked );

//					if ( bChecked ) selectOption( eusFront, euoImage );
				}
				bUpdateNeeded = true;
				break;
			case eueUvImageBack_Changed:
				{
					bool bChecked = isChecked( IDC_CB_UV_IMAGE_BACK ) && isEnabled( IDC_CB_UV_IMAGE_BACK ) ? true : false;
					bool bEnableB = m_lImageBack ? true : false;
					m_SC.SetID( IDC_EF_UV_IMAGE_BACK, bChecked );
					m_SC.SetID( IDC_PB_UV_IMAGE_BACK, bChecked );
					m_SC.SetID( IDC_PIC_UV_IMAGE_BACK, bChecked );

//					if ( bChecked ) selectOption( eusBack, euoImage );
				}
				bUpdateNeeded = true;
				break;

			case eueUvAreaFront_Changed:
				bChecked = isChecked( IDC_CB_UV_AREA_FRONT ) ? true : false;
				m_SC.SetID( IDC_PIC_UV_AREA_FRONT, bChecked );
//				if ( bChecked ) selectOption( eusFront, euoArea );
				bUpdateNeeded = true;
				break;

			case eueUvAreaBack_Changed:
				bChecked = isChecked( IDC_CB_UV_AREA_BACK ) && isEnabled( IDC_CB_UV_AREA_BACK ) ? true : false;
				m_SC.SetID( IDC_PIC_UV_AREA_BACK, bChecked );
//				if ( bChecked ) selectOption( eusBack, euoArea );
				bUpdateNeeded = true;
				break;

			case eueUvSecondPageFront_Changed:
//				if ( GetCheck( IDC_CB_UV_SECOND_PAGE_FRONT ) ) selectOption( eusFront, euoSecondPage );
				break;

			case eueUvSecondPageBack_Changed:
//				if ( GetCheck( IDC_CB_UV_SECOND_PAGE_BACK ) ) selectOption( eusBack, euoSecondPage );
				break;


			case eueUvAreaFront:
				EditArea( &m_picAreaFront, 0, (int)esFront );
				break;

			case eueUvAreaBack:
				EditArea( &m_picAreaBack, 0, (int)esBack );
				break;

		}


		if ( !m_bUpdateLocked && bUpdateNeeded )
		{
#ifdef XXX
			if ( !bEncodeOnly )
			{
				// refresh DEVMODE structure to represent the current setting-state in the input-image
				DisplayToDevmod();	// do not call UpdateData( DISPLAY2DATA ) since this is already done and would overwrite our values
/*
				pCommon_->pStateMachine->Evaluate( m_lpDM );
				bool bCanSaveMaterial = pCommon_->pStateMachine->bCanSaveMaterial;
				// if Material cannot be saved, disable checkbox...
				m_SC.SetID( IDC_CB_EP_USAGE_SAVEMATERIAL, bCanSaveMaterial );
				// ...and clear the check
				if ( !bCanSaveMaterial ) m_lSaveMaterial = 0;
				m_iInkCount = pCommon_->pStateMachine->iInkCount;
				m_iRetransferCount = pCommon_->pStateMachine->iRetransferCount;
*/

			}
#endif // XXX
			UpdateImages();
			m_SC.RestoreControlState( this, bEncodeOnly || m_bProhibit_560_570_Features );
		}

		UpdateData( DATA2DISPLAY );

		bUpdateRunning = false;
	}
}

void CUvPropPage::UpdateImages()
{
	::PostMessage( GetSafeHwnd(), WM_UPDATE_CONTROL, 0, 0);
}

void CUvPropPage::fitRect( POINT &outer, RECT &inner, const POINT dst )
{
	POINT outerRes;
	RECT innerRes;
	DWORD dwOuterX = outer.x * dst.y / outer.y;
	bool bDstIsHigherThanOuter = dwOuterX < (DWORD)dst.x ? true : false;

	if ( bDstIsHigherThanOuter )
	{
		outerRes.x = dwOuterX;
		outerRes.y = dst.y;
	} else {
		outerRes.x = dst.x;
		outerRes.y = outer.y * dst.x / outer.x;
	}
	innerRes.left = inner.left * outerRes.x / outer.x;
	innerRes.top = inner.top * outerRes.y / outer.y;
	innerRes.right = inner.right * outerRes.x / outer.x;
	innerRes.bottom = inner.bottom * outerRes.y / outer.y;

	outer = outerRes;
	inner = innerRes;
}

bool CUvPropPage::browseForBmpFile( CString *pstrImagePath )
{
	bool bRet = false;

	// Init the File open dialog.
	CFileDialog dlgFile( TRUE, // create an "open file" dialog
		_T( "*.BMP" ), // default extension
		*pstrImagePath, // default filename is current text
		OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, // flags
		_LOC( "Bitmaps (*.bmp)" ) + _T( "|*.bmp||" ) // filter
	);

	//	cDlg.m_ofn.lpstrInitialDir = NULL; // "\\\\My Pictures\\";

	if ( dlgFile.DoModal() == IDOK )
	{
		*pstrImagePath = dlgFile.m_ofn.lpstrFile;
		bRet = true;
	}

	return bRet;
}

EUVLOADERROR CUvPropPage::loadUvFromImage( LPCTSTR pszFileName, MGBITMAP **m_pBmpUvImage, bool bShowError )
{
	EUVLOADERROR Ret = eleLoadError;
	bool bIsPortrait = m_lpDM->rasdm.dmOrientation == DMORIENT_PORTRAIT;
//	MGBITMAP *m_pBmpUvImage = Event == eueUvImageFrontChanged ? &m_pBmpUvImageFront : &m_pBmpUvImageBack;
	DWORD dwSrcWidth = bIsPortrait ? TheHeight : TheWidth,
		dwSrcHeight = bIsPortrait ? TheWidth : TheHeight;
	// reload image
	if ( *m_pBmpUvImage )
	{
		MG_Unload( *m_pBmpUvImage );
		*m_pBmpUvImage = 0;
	}
	MGBITMAP *pBmpBig;

	pBmpBig = loadBmpToBitmapPtr( pszFileName, pPaletteUv4_ );

	if ( pBmpBig )
	{
		DWORD dwFileWidth = MG_GetWidth( pBmpBig ),
			dwFileHeight = MG_GetHeight( pBmpBig );
		if ( dwFileWidth == dwSrcWidth && 
			dwFileHeight == dwSrcHeight )
		{
			CRect rect;
			m_picImageBack.GetWindowRect( &rect );
			DWORD dwDstWidth = rect.Width(),
				dwDstHeight = rect.Height();

			*m_pBmpUvImage = MG_Allocate( rect.Width(), rect.Height() );
			POINT fitOuter = { dwSrcWidth, dwSrcHeight },
				fitDst = { dwDstWidth, dwDstHeight };
			RECT fitInner = { 0, 0, dwSrcWidth, dwSrcHeight };
			fitRect( fitOuter, fitInner, fitDst );

			MG_setColor( chroma );
			MG_Box( *m_pBmpUvImage, 0, 0, dwDstWidth, dwDstHeight );

			// draw black frame around image
			DWORD rgb = 0xff000000; MG_setColor( (BYTE *)&rgb );
			MG_Frame( *m_pBmpUvImage, fitInner.left, fitInner.top, fitInner.right, fitInner.bottom, 1 );

			MG_CopyResizedC( *m_pBmpUvImage, pBmpBig, 0, 0, dwSrcWidth, dwSrcHeight,
				fitInner.left + 1, fitInner.top + 1, fitInner.right - 2, fitInner.bottom - 2 );
			Ret = eleNoErr;
		} else {
			Ret = eleWrongDimension;
			if ( bShowError )
			{
				CString strTemp;
				strTemp.Format( _LOC( "Image must be %d x %d pixels, but is %d x %d!" ), dwSrcWidth, dwSrcHeight, dwFileWidth, dwFileHeight );
				AfxMessageBox( strTemp );
			}
		}

		MG_Unload( pBmpBig );
	} else {
//		Ret = eleLoadError; is already default error
		if ( bShowError )
		{
			AfxMessageBox( _LOC( "Could not load image file (not BMP format?)" )  );
		}
	}

	return Ret;
}

void CUvPropPage::generateNewPathIndexesIfNecessary()
{
	if ( m_dwPathIndexFront == 0 && m_dwPathIndexBack == 0 )
	{
		m_IniPathIndex.getNewPathIndex( &m_dwPathIndexFront );
		m_IniPathIndex.getNewPathIndex( &m_dwPathIndexBack );
	}
}

bool CUvPropPage::setUvFromImageForSide( LPCTSTR pszUvBmpFile, EUVSIDE Side, bool bShowError )
{
	bool bRet = false;
	if ( Side == eusFront )
	{
		if ( _tcslen( pszUvBmpFile ) )
		{
			if ( loadUvFromImage( pszUvBmpFile, &m_pBmpUvImageFront, bShowError ) == eleNoErr )
			{
				bRet = true;
				// store display name (filename only) and full path in different variables
				CFile64::ExtractFileName( m_strImageFront, pszUvBmpFile );
			}
		}
	} else {
		if ( _tcslen( pszUvBmpFile ) )
		{
			if ( loadUvFromImage( pszUvBmpFile, &m_pBmpUvImageBack, bShowError ) == eleNoErr )
			{
				bRet = true;
				// store display name (filename only) and full path in different variables
				CFile64::ExtractFileName( m_strImageBack, pszUvBmpFile );
			}
		}
	}

	return bRet;
}

void CUvPropPage::setOrientation()
{
	bool bToPortrait = m_lpDM->rasdm.dmOrientation == DMORIENT_PORTRAIT;
	if ( bToPortrait )
	{
		xImage_ = TheHeight;
		yImage_ = TheWidth;
	} else {
		xImage_ = TheWidth;
		yImage_ = TheHeight;
	}

	// set image orientation
	if ( m_bInitialized )
	{
		// get areas from current DEVMODE structure (i.e. the areas are already rotated in Layout page)
		setAreasToArrayFromDevmod( &Areas_[ 0 ][ esFront ], &m_lpDM->UvAreas[ 0 ], nAreaCountMax_ );
	}

	{ // update thumbnail orientation
		CRect rect;

		tvExclusionST2::const_iterator it = vpAreaST_.begin(),
			end = vpAreaST_.end();
		CExclusionST2 *pWnd;

		while ( it != end )
		{
			pWnd = *it++;

			pWnd->GetWindowRect( &rect );
			GetParent()->ScreenToClient( &rect );
			pWnd->SetSize( rect.Width(), rect.Height(),
				xImage_, yImage_, nDPI_ );
		}
	}

	m_pInclusionDlgOffset->SetImageRes( xImage_, yImage_, nDPI_ );		// orientation may have been changed

}

void CUvPropPage::OnPicAreaFront()
{
	UpdateControls( eueUvAreaFront );
}

void CUvPropPage::OnPicAreaBack()
{
	UpdateControls( eueUvAreaBack );
}

void CUvPropPage::EditArea( CExclusionST2 *pPic, int iPanel, int iSide )
{
	m_pInclusionDlgOffset->m_picExclusion.SetExclusionAreasFrom( &Areas_[ iPanel ][ iSide ] );	// set area information from preview thumb

/*
	m_pModalPic = pPic;
	m_iModalPanel = iPanel;
	m_iModalSide = iSide;
*/

	if ( m_pInclusionDlgOffset->DoModal() == IDOK )
	{
		m_pInclusionDlgOffset->m_picExclusion.GetExclusionAreasTo( &Areas_[ iPanel ][ iSide ] );
		pPic->SetExclusionAreasFrom( &Areas_[ iPanel ][ iSide ] );

		pPic->ForceRedraw();
	}
}

// initialize variables, control IDs and events for UV options
// (only one allowed at a time per side)
void CUvPropPage::setupOptions()
{
	SOptionSelector OptionSelector;

	{
		OptionSelector.pbVar = &m_lImageFront;
		OptionSelector.ControlID = IDC_CB_UV_IMAGE_FRONT;
		OptionSelector.Event = eueUvImageFront_Changed;
		vOptionSelector_[ eusFront ].push_back( OptionSelector );

		OptionSelector.pbVar = &m_lAreaFront;
		OptionSelector.ControlID = IDC_CB_UV_AREA_FRONT;
		OptionSelector.Event = eueUvAreaFront_Changed;
		vOptionSelector_[ eusFront ].push_back( OptionSelector );

		OptionSelector.pbVar = &m_lSecondPageFront;
		OptionSelector.ControlID = IDC_CB_UV_SECOND_PAGE_FRONT;
		OptionSelector.Event = eueUvSecondPageFront_Changed;
		vOptionSelector_[ eusFront ].push_back( OptionSelector );
	}

	{
		OptionSelector.pbVar = &m_lImageBack;
		OptionSelector.ControlID = IDC_CB_UV_IMAGE_BACK;
		OptionSelector.Event = eueUvImageBack_Changed;
		vOptionSelector_[ eusBack ].push_back( OptionSelector );

		OptionSelector.pbVar = &m_lAreaBack;
		OptionSelector.ControlID = IDC_CB_UV_AREA_BACK;
		OptionSelector.Event = eueUvAreaBack_Changed;
		vOptionSelector_[ eusBack ].push_back( OptionSelector );

		OptionSelector.pbVar = &m_lSecondPageBack;
		OptionSelector.ControlID = IDC_CB_UV_SECOND_PAGE_BACK;
		OptionSelector.Event = eueUvSecondPageBack_Changed;
		vOptionSelector_[ eusBack ].push_back( OptionSelector );
	}
}

// if checkbox is checked, select one of the options (if a checkbox if checked, uncheck all the others)
// otherwise return false (checkbox was unchecked during calling)
//
// If the control will be enabled
// This disables all other enabled options and updates the disabled control
// and enables or disables the selected option
void CUvPropPage::selectOption( EUVSIDE Side, EUVOPTION Option, BOOL bEnable )
{
	size_t i,
		iSelected = Option;

	// disable other options
	if ( bEnable )
	{
		for ( i = 0; i < euoEnd; ++i )
		{
			SOptionSelector *pOptionSelector = &vOptionSelector_[ Side ][ i ];
			if ( i != iSelected && *pOptionSelector->pbVar )
			{
				*pOptionSelector->pbVar = FALSE;
				SetCheck( pOptionSelector->ControlID, FALSE );
				UpdateControls( pOptionSelector->Event );
			}
		}
	}

	// enable (or disable) selected option
	SOptionSelector *pOptionSelector = &vOptionSelector_[ Side ][ iSelected ];
	*pOptionSelector->pbVar = bEnable;
	SetCheck( pOptionSelector->ControlID, bEnable );
	// update control unconditionally (i.e. when called for initialization)
	UpdateControls( pOptionSelector->Event );
}
